/***
    Amrita ITEWS - Copyright (C) 2009 Amrita Vishwa Vidyapeetham, Amritapuri.
                                       (http://www.amrita.edu)
    ***************************************************************************
    This file is part of the Amrita ITEWS distribution.
    Amrita ITEWS is free software; you can redistribute it and/or modify it 
    under the terms of the GNU General Public License (version 2) as published
    by the Free Software Foundation AND MODIFIED BY the Amrita ITEWS exception.
    ***NOTE*** The exception to the GPL is included to allow you to distribute
    a combined work that includes Amrita ITEWS without being obliged to provide
    the source code for proprietary components outside of the Amrita ITEWS
    software. Amrita ITEWS is distributed in the hope that it will be useful, 
    but WITHOUT ANY WARRANTY; without even the implied warranty of 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
    Public License for more details. You should have received a copy of the GNU
    General Public License and the Amrita ITEWS license exception along with 
    Amrita ITEWS if not then it can be viewed here: 
    http://itews.amrita.ac.in/license.html.

    Documentation, latest information, license and contact details are at:
    http://itews.amrita.ac.in/

    Amrita ITEWS source code can be found at:
    http://code.google.com/p/itews

    The initial code-base of Amrita ITEWS was developed by Amrita Vishwa 
    Vidyapeetham as part of the project titled,"Intelligent & Interactive 
    Telematics using Emerging Wireless Technologies for Transport Systems 
    (ITEWS)" sponsored by Technology Information Forecasting and Assessment 
    Council (TIFAC), India.
***/
package baseplatformservices;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Hashtable;
import org.knopflerfish.service.log.LogRef;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;

public class Activator implements  BundleActivator, EventHandler
{
	protected static final String E_TAG = "ETag";
	protected static final String MSG_ID = "msgId";
	protected static final String TIME_STAMP = "Last-Modified";
	protected static final String APP_SERVICE_NAME = "appname";
	private BasePlatformConfig config = null;
	public static BundleContext bc = null;	
	private WifiNodeLocatorSubscriber wifiNodeLocatorSubscriber;
	private BlogSubscriber blogSubscriber;
	private BlogPublisher blogPublisher;
	private EventAdmin eventAdmin;
	private  LogRef log;
	private ServiceRegistration publisherEventHandlerService; 
	private ServiceRegistration subscriberEventHandlerService; 
	private DBConnectionPool dbConnectionPool ;
	private String eTagQuery = "Select * from etag_table where app_name =?";
	private String eTagInsert = "Insert into etag_table (id, etag, timestamp, app_name) Values (default, ?, ?, ?)";
	private String eTagUpdate = "Update etag_table set etag = ?, timestamp = ? where app_name = ?";

	public void start(BundleContext bc) throws Exception
	{
		Activator.bc = bc;
		log = new LogRef(bc);
		try
		{
			config = BasePlatformConfig.getConfig();
		}
		catch(Exception e)
		{
			log.error(bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME)+ " failed to start due to configuration file setup error.");
			Activator.bc = null;
			throw e;
		}
		try
		{
		ServiceReference reference = bc.getServiceReference (EventAdmin.class.getName());
		eventAdmin = (EventAdmin) bc.getService(reference);
		dbConnectionPool = DBConnectionPool.getInstance(config.getJdbcConnectionURI());
		
		blogSubscriber = new BlogSubscriber(eventAdmin);
		blogSubscriber.start();
		Hashtable ht2 = new Hashtable();
		String[] appEventTopics = new String[] {config.getEventTopicToBPSBundle()};
		ht2.put(EventConstants.EVENT_TOPIC, appEventTopics);
		subscriberEventHandlerService = bc.registerService(EventHandler.class.getName(), this, ht2);
		
		blogPublisher = new BlogPublisher();
		blogPublisher.start();
		
		/**
		Currently disabled 
		wifiNodeLocatorSubscriber = new WifiNodeLocatorSubscriber(eventAdmin);
		wifiNodeLocatorSubscriber.start();
		*/
		
		System.out.println(bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME)+ " started.");
		}
		catch(Exception e)
		{
			log.error("baseplatformservices failed to start");
			e.printStackTrace();
		}
	}
	
	public synchronized void handleEvent(Event event) 
	{
		String eventTopic = event.getTopic();
		if (eventTopic.equals(config.getEventTopicToBPSBundle()))
		{
			String appName = (String) event.getProperty(APP_SERVICE_NAME);
			log.info("Received bundle event from " + appName + " application for updating eTag in DB");
		    long etag = (Long) event.getProperty(E_TAG);
		    long timestamp = (Long) event.getProperty(TIME_STAMP);
		    Connection conn = null;
		    ResultSet rs1 = null;
		    PreparedStatement preparedStmt1 = null;
		    PreparedStatement preparedStmt2 = null;
	    	try 
	    	{
	    		conn = dbConnectionPool.getConnection();
	    		conn.setAutoCommit(false);
	    		preparedStmt1 = dbConnectionPool.getPreparedStmt(conn, eTagQuery);
	    		preparedStmt1.setString(1, appName);
	    		rs1 = preparedStmt1.executeQuery();
	    		if (rs1.next())
	    		{
	    			preparedStmt2 = dbConnectionPool.getPreparedStmt(conn, eTagUpdate);
	    		}
	    		else
	    		{
	    			preparedStmt2 = dbConnectionPool.getPreparedStmt(conn, eTagInsert);
	    		}
				preparedStmt2.setLong(1, etag);
				preparedStmt2.setLong(2, timestamp);
				preparedStmt2.setString(3, appName);
				preparedStmt2.executeUpdate();
				preparedStmt2.close();	
				preparedStmt2 = null;
				rs1.close(); 
				rs1 = null;
				preparedStmt1.close();
				preparedStmt1 = null;
		    	conn.commit();
			}
	    	catch (Exception e) 
			{
				log.error("Error while handling bundle events in Base Platform services");
	    		e.printStackTrace();
			}
			finally
			{
	    		if (rs1 != null)
	    		{
	    			try {rs1.close();} catch (SQLException e) {} 
	    			rs1 = null;
	    		}
	    		if (preparedStmt1 != null)
	    		{
	    			try {preparedStmt1.close();} catch (SQLException e) {} 
	    			preparedStmt1 = null;
	    		}
	    		if (preparedStmt2 != null)
	    		{
	    			try {preparedStmt2.close();} catch (SQLException e) {} 
	    			preparedStmt2 = null;
	    		}
				if (conn != null)
				{
					try {conn.close();} catch (SQLException e) {}
					conn = null;
				}
			}
		}
	}

	public void stop(BundleContext context) throws Exception 
	{
		BasePlatformConfig.singleton = null;
		if (publisherEventHandlerService!=null)
			publisherEventHandlerService.unregister();
		publisherEventHandlerService = null;
		if (subscriberEventHandlerService!=null)
			subscriberEventHandlerService.unregister();
		subscriberEventHandlerService = null;
		if (blogSubscriber != null)
			blogSubscriber.stopThread();
		blogSubscriber = null;
		if (blogPublisher != null)
			blogPublisher.stopThread();
		blogPublisher = null;
		if (wifiNodeLocatorSubscriber != null)
			wifiNodeLocatorSubscriber.stopThread();
		wifiNodeLocatorSubscriber = null;
		System.out.println(bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME)+ " stopped!");
		Activator.bc = null;
	}
}
